var gNavData;
var gSpine;
var gNavPath;

//nav heading object
function navheading(id, level, label, contentsrc)
{
	this.level = level;
	//trim the label
	this.label = label.replace(/^\s+/g, '').replace(/\s+$/g, '');
	this.contentSrc = contentsrc;
	this.id = id;
}

function addToSpine(file, files)
{
	//strip target
	var smilfile = file;
	var idx = smilfile.indexOf("#");
	if (idx > -1) smilfile = smilfile.substring(0, idx);
	
	//if this is the only file, then we don't need to check for duplicates
	if (files.length == 0) 
	{
		files[0] = smilfile;
		return;
	}
	
	//check for duplicates.. the spine should have only one entry per smil reference
	var found = false;
	for (var i = 0; i<files.length; i++)
	{
		if (files[i] == smilfile)
		{
			found = true;
			return;
		}
	}
	if (!found) files[i] = smilfile;
}

//parse an ncc.html file
//	localFile is an nsILocalFile type
function loadnav(localFile)
{
	//the file as a stream
	var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"].
				            createInstance(Components.interfaces.nsIFileInputStream);
	
	var xmlReader = Components.classes["@mozilla.org/saxparser/xmlreader;1"]
	                          .createInstance(Components.interfaces.nsISAXXMLReader);

	fstream.init(localFile, -1, 0, 0);
	var count = 0;
	var spineCount = 0;
	var inHeading = false;
	var headinglevel = 0;
	var headinglabel = "";
	var headingid = "";
	var level = 0;
	var headinghref = "";
	var headingdata;
	
	gNavData = new Array();
	gSpine = new Array();
	
	xmlReader.contentHandler = 
	{
		startElement: function(uri, localName, qName, /*nsISAXAttributes*/ attributes) 
		{
			level = isHeading(qName);
			if (level > 0)
			{
				inHeading = true;
				headinglevel = level;
				headinglabel = "";
				headingid = attributes.getValueFromQName("id");
			}
			else if (qName == "a")
			{
				if (inHeading)
				{
					headinghref = attributes.getValueFromQName("href");
					addToSpine(headinghref, gSpine);
				}
			}
		},

		endElement: function(uri, localName, qName) 
		{
	    	if (isHeading(qName))
			{
				inHeading = false;
				headingdata = new navheading(headingid, headinglevel, headinglabel, headinghref);
				gNavData[count] = headingdata;
				count++;
			}
		},
		
		startDocument: function() {
		// don't care
		},

		  endDocument: function() {
		   	// don't care
		  },

		characters: function(value) 
		{
			if (inHeading) headinglabel += value;
		},

		  processingInstruction: function(target, data) {
		    	// don't care
		  },

		  ignorableWhitespace: function(whitespace) {
		    // don't care
		  },

		  startPrefixMapping: function(prefix, uri) {
		    // don't care
		  },

		  endPrefixMapping: function(prefix) {
		    // don't care
		  },

		  // nsISupports
		  QueryInterface: function(iid) {
		    if(!iid.equals(Components.interfaces.nsISupports) &&
		       !iid.equals(Components.interfaces.nsISAXContentHandler))
		      throw Components.results.NS_ERROR_NO_INTERFACE;
		    return this;
		  }
	};

	xmlReader.parseFromStream(fstream,"", "text/xml");
}
//obviously there's a more elegant way to do this; right now i don't care though
function isHeading(tagname)
{
	if (tagname == "h1") return 1;
	else if (tagname == "h2") return 2;
	else if (tagname == "h3") return 3;
	else if (tagname == "h4") return 4;
	else if (tagname == "h5") return 5;
	else if (tagname == "h6") return 6;
	else return 0;
}

//open a file
//	filepath is an nsILocalFile object
function opennav(filepath)
{	
	gNavPath = filepath;
	gBookDirectory = gNavPath.parent.path;
	loadnav(filepath, "");
//	printlist(gNavData);
//	printspine(gSpine);
	if (gNavData.length == 0) return false;
	else return true;
}

//debug printing functions
function printlist(data)
{
	alert ("printing " + data.length + " items");
	for (var i = 0; i<data.length; i++)
	{
		alert(data[i].label);
	}
}
function printspine(data)
{
	alert ("printing spine, " + data.length + " items");
	for (var i = 0; i<data.length; i++)
	{
		alert(data[i]);
	}
}